package com.xiaobai.upload;

import com.xiaobai.common.base.BaseResponse;
import com.xiaobai.common.base.CommonRuntimeException;
import com.xiaobai.common.base.ErrorCode;
import com.xiaobai.util.FileUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.util.stream.Stream;

/**
 * 资源上传Controller
 *
 * @author bail
 * @date 2019/12/16
 */
@Api(tags = "UploadController-资源上传API")
@RestController()
@RequestMapping("/resource")
@Validated
@Slf4j
public class UploadController {

    /**
     * 上传图片的物理路径前缀
     */
    public static final String DIR_PATH_PREFIX = "/data/bb_dish_front/dishimg";
    /**
     * 上传菜品图片的逻辑目录前缀
     */
    private static final String DISH_PREFIX = "/dish";
    /**
     * 上传用户头像的逻辑目录前缀
     */
    private static final String USER_PHOTO_PREFIX = "/user_photo";
    /**
     * 限制文件后缀名
     */
    private static final String FILE_SUFFIX = ".jpg,.jpeg,.png,.gif";
    /**
     * 限制文件大小 2MB
     */
    private static final long FILE_SIZE_LIMIT = 2L * 1024L * 1024L;

    @ApiOperation(value = "资源上传", notes = "目前是上传后,返回相对路径给前端,并没有入库,若用户放弃保存返回的url,则存在脏文件")
    @PostMapping("/upload")
    public BaseResponse resourceUpload(@ApiParam(required = true, example = "/xxx.jpg") @RequestParam MultipartFile file,
    @ApiParam(required = true, example = "1") @RequestParam int type) {
        String dirPrefix;
        if (type == 1) {
            dirPrefix = DISH_PREFIX;
        } else {
            dirPrefix = USER_PHOTO_PREFIX;
        }

        // 检查文件格式并返回后缀名
        String ext = this.checkFileFormat(file);
        // 检查文件大小
        this.checkFileSize(file);

        // 资源上传后的相对路径
        String picPath = dirPrefix + "/"
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM")) + "/"
                + UUID.randomUUID() + ext;

        // 创建本地文件
        File targetFile = FileUtil.newFile(DIR_PATH_PREFIX + picPath);

        try {
            // 将上传的文件写到服务器上指定的文件
            file.transferTo(targetFile);
        } catch (Exception e) {
            log.error("resourceUpload资源上传失败", e);
            return BaseResponse.FAILED();
        }
        return BaseResponse.success(picPath);
    }

    /**
     * 检查文件格式,并返回后缀名
     *
     * @param file 待检查的文件
     * @return 文件后缀名
     */
    private String checkFileFormat(MultipartFile file) {
        if (file.getOriginalFilename() == null) {
            throw new CommonRuntimeException(ErrorCode.COMMON_FAIL, "文件名不能为空");
        }

        if (Stream.of(FILE_SUFFIX.split(",")).noneMatch(s -> file.getOriginalFilename().toLowerCase().endsWith(s))) {
            throw new CommonRuntimeException(ErrorCode.COMMON_FAIL, String.format("文件后缀名必须是%s", FILE_SUFFIX));
        }

        return file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
    }

    /**
     * 检查文件大小
     *
     * @param file 待检查的文件
     */
    private void checkFileSize(MultipartFile file) {
        long fileSize = file.getSize();
        if (fileSize > FILE_SIZE_LIMIT) {
            throw new CommonRuntimeException(ErrorCode.COMMON_FAIL, String.format("文件必须小于%s", FileUtil.getFileSizeStr(FILE_SIZE_LIMIT)));
        }
    }
}
